#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>

//nc -u -l 172.27.1.12 60000
//nc -u 172.27.1.12 50000
int main(int argc, const char *argv[])
{
    int tcp_socket, con_socket, ret_recv;
    struct sockaddr_in myaddr, peeraddr;
    char buf[128] = {0};
    int len;
    tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(tcp_socket < 0) {
        perror("fail to socket");
        exit(1);
    }

    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(50000);
    myaddr.sin_addr.s_addr = inet_addr("172.27.1.12");

    if(-1 == bind(tcp_socket, (struct sockaddr*)&myaddr, sizeof(myaddr))) {
        perror("fail to bind");
        exit(1);
    }

    //LISTEN
    //int listen(int sockfd, int backlog);
    //将 tcp_socket 转换成被动模式：用于监听即将到来的连接请求
    //为 accept 函数做准备
    //backlog 5  定义内核中等待队列的长度，一般写5，高版本内核只作为参考值
    //当连接到来时，如果 backlog 满了，那么客户端会报错误:ECONNEFUSED
    //(连接拒绝)
    if(-1 == listen(tcp_socket, 5)) {
        perror("fail to listen");
        exit(1);
    }
    len = sizeof(peeraddr);
    printf("len:%d\n", len);
    while(1) {
        printf("while\n");
        con_socket = accept(tcp_socket, (struct sockaddr*)&peeraddr, &len);
        if(con_socket == -1) {
            perror("fail to accept");
            exit(1);
        }
        printf("accept\n");
        printf("peer ip:%s port:%d is connected!\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
        while(1) {
            bzero(buf, sizeof(buf));
            ret_recv = recv(con_socket, buf, sizeof(buf), 0);
            if(ret_recv < 0) {
                perror("fail to recv");
                exit(1);
            } else if(ret_recv == 0) {
                printf("%s is shutdown !\n", inet_ntoa(peeraddr.sin_addr));
                close(con_socket);
            } else {
                printf("recv:%s\n", buf);
            }
        }
    }
    close(tcp_socket);

    return 0;
}

